package com.mrogrape.gui;

import java.awt.Graphics;
import java.awt.LayoutManager;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JPanel;



public class AnimationPanel extends JPanel{

	/** serialVersionUID */
	private static final long serialVersionUID = 1L;

	/**
	 * {@inheritDoc}
	 */
	public AnimationPanel() {
		super();
	}
	
	/**
	 * {@inheritDoc}
	 */
	public AnimationPanel(boolean isDoubleBuffered) {
		super(isDoubleBuffered);
	}
	
	/**
	 * {@inheritDoc}
	 */
	public AnimationPanel(LayoutManager layout) {
		super(layout);
	}

	/**
	 * {@inheritDoc}
	 */
	public AnimationPanel(LayoutManager layout, boolean isDoubleBuffered) {
		super(layout, isDoubleBuffered);
	}
	
	/**
	 * 创建一个Banner并指定动画绘制器。
	 * 
	 * @param painter 指定的动画绘制器对象
	 */
	public AnimationPanel(AnimationPainter painter) {
		super();
	}
	
	/**
	 * 获取动画帧之间的延迟。
	 * 
	 * @return 动画的延迟时间，以毫秒为单位。
	 */
	public int getAnimationDelay() {
		return this.animationDelay;
	}

	/**
	 * 设置动画帧之间的延迟。
	 * 
	 * @param animationDelay 动画的延迟时间，以毫秒为单位。不可为非正数。
	 */
	public void setAnimationDelay(int animationDelay) {
		if(animationDelay <= 0){
			throw new IllegalArgumentException("Delay can not be zero or less than.");
		}
		this.animationDelay = animationDelay;
		
		if(this.isAnimationStarted()){
			this.cancelPaint();
			this.startPaint();
		}
	}

	/**
	 * 获取用于绘制动画的动画绘制器。
	 * 
	 * @return 用于绘制动画的动画绘制器。
	 */
	public AnimationPainter getAnimationPainter() {
		return this.animationPainter;
	}

	/**
	 * 设置用于绘制动画的动画绘制器。
	 * 
	 * @param animationPainter 用于绘制动画的动画绘制器。
	 */
	public void setAnimationPainter(AnimationPainter animationPainter) {
		this.animationPainter = animationPainter;
	}

	/**
	 * 查看是否已经开始绘制动画。
	 * 
	 * @return 是否已经开始绘制动画，true的场合为已经开始绘制。
	 */
	public boolean isAnimationStarted() {
		return this.animationStarted;
	}

	/**
	 * 设置是否开始动画。
	 * 
	 * @param isAnimationStarted 是否已经开始绘制动画，true的场合为开始绘制。
	 */
	public void setAnimationStarted(boolean isAnimationStarted) {
		boolean orginalValue = this.animationStarted;
		this.animationStarted = isAnimationStarted;
		
		if(isAnimationStarted == orginalValue){
			return;
		}
		
		if(isAnimationStarted){
			this.startPaint();
		}else{
			this.cancelPaint();
		}
	}
	
	/**
	 * 获取动画绘制的速度，以
	 * 
	 * @return 动画绘制的速度，以FPS为单位。
	 */
	public int getAnimationSpeed(){
		
		return 1000/ this.animationDelay;
	}
	
	/**
	 * 设置动画绘制的速度，以FPS为单位。
	 * 
	 * @param fps 动画绘制的速度，以FPS为单位，不可小于等于0。 
	 */
	public void setAnimationSpeed(int fps){
		
		if(fps <= 0){
			
			throw new IllegalArgumentException("FPS cannot be 0 or less than it.");
		}
		
		this.setAnimationDelay(1000 / fps + 1);
	}
	
	@Override
	protected void paintComponent(Graphics g) {

		// 绘制背景色
		super.paintComponent(g);
		
		// 通知动画绘制器绘制当前帧
		if(this.animationPainter != null){
			
			this.animationPainter.paintCurrentFrame(g, 0, 0, this.getWidth(), this.getHeight(), this.resetAnimationFlg, !this.isOnSchedule);
			if(this.resetAnimationFlg){
				this.resetAnimationFlg = false;
			}
		}
		
		// 重置预约动画标记
		this.isOnSchedule = false;
	}
	
	/**
	 * 取消动画绘制
	 */
	private void cancelPaint(){
		
		this.paintTask.cancel();
		this.paintTask = null;
		this.timer.purge();
	}
	
	/**
	 * 开始动画绘制
	 */
	private void startPaint(){
		
		this.paintTask = new RepaintTask();
		this.timer.scheduleAtFixedRate(this.paintTask, 10, this.animationDelay);
	}
	
	private int animationDelay = 25;
	private AnimationPainter animationPainter= null;
	private RepaintTask paintTask = new RepaintTask();
	private Timer timer = new Timer();
	
	private boolean animationStarted = false;
	private boolean resetAnimationFlg = true;
	private boolean isOnSchedule = false;
	
	private class RepaintTask extends TimerTask{

		@Override
		public void run() {
			AnimationPanel.this.isOnSchedule = true;
			repaint();
		}
	}
}
